/*
 *  Copyright (c) 2011 Leibniz Institute of Plant Genetics and Crop Plant Research (IPK), Gatersleben, Germany.
 *  All rights reserved. This program and the accompanying materials
 *  are made available under the terms of the GNU Lesser Public License v2.1
 *  which accompanies this distribution, and is available at
 *  http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 *
 *  Contributors:
 *      Leibniz Institute of Plant Genetics and Crop Plant Research (IPK), Gatersleben, Germany - RMI Client, FileChooser and WebDAV
 */
package de.ipk_gatersleben.bit.bi.edal.rmi.client.gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.util.Calendar;
import java.util.Date;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JSpinner;
import javax.swing.JTextField;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.border.LineBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import net.miginfocom.swing.MigLayout;

import de.ipk_gatersleben.bit.bi.edal.primary_data.metadata.EdalDate;
import de.ipk_gatersleben.bit.bi.edal.primary_data.metadata.EdalDatePrecision;
import de.ipk_gatersleben.bit.bi.edal.rmi.client.util.Const;
import de.ipk_gatersleben.bit.bi.edal.rmi.client.util.EdalDateFormat;
import de.ipk_gatersleben.bit.bi.edal.rmi.client.util.ImageUtil;
/**
 * <code>DatetimePicker</code> provides a swing panel for the user to choose Datetime and set it's Precision.
 * <p>
 * 
 * The following codes show how to user it:
 * 
 * <pre>
 * DatetimePicker starttimepicker = new DatetimePicker(null);
 * Calendar startcalendar = starttimepicker.getCalendar();
 * EDALDatePrecision starttimeprecision = starttimepicker.getPrecision();
 * </pre>
 * <p>
 * 
 * 
 * @version 1.0
 * @author Jinbo Chen
 * 
 */
public class EdalDateTimePicker extends JPanel {
	private static final long serialVersionUID = 1L;
	private static final Font FONT = new Font("Courier New", Font.PLAIN, 12);
	private DateChooser dateChooser = null;
	private Calendar showcalendar;
	private Calendar _calendar;
	private EdalDatePrecision showprecision;
	private EdalDatePrecision _precision;
	private JTextField text;
	private JLabel label;
	
	/**
     * Constructs a <code>DatetimePicker</code> that is initialized with
     * <code>edaldate</code>.
     * If the parameter are <code>null</code> this method
     * will initialize the DatetimePicker with current time and 
     * EDALDatePrecision.SECOND as default Precision.
     *
     * @param edaldate      EDALDate object to show in DatetimePicker panel
     */ 

	public EdalDateTimePicker(EdalDate edaldate) {
		if (edaldate != null) {
			this.showcalendar = edaldate.getStartDate();
			this.showprecision = edaldate.getStartPrecision();
		} else {
			this.showcalendar = Calendar.getInstance();
			this.showprecision = EdalDatePrecision.SECOND;
		}
		setBorder(null);
		setCursor(new Cursor(Cursor.HAND_CURSOR));
		
		setLayout(new MigLayout("","[20%!][20%!][20%!][20%!]1[20%!]",""));
		text = new JTextField();
		text.setHorizontalAlignment(JTextField.CENTER);
		text.setEditable(false);
		add(text,"cell 0 0 4 1,width max(80%, 80%)");

		ImageIcon icon = ImageUtil.createImageIcon("dateIcon.gif","choose new datetime");
		label = new JLabel(icon);
		label.setToolTipText("choose new datetime");
		add(label,"cell 4 0 1 1");

		label.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent e) {
				if (dateChooser == null) {
					dateChooser = new DateChooser();
				}
				Point p = getLocationOnScreen();
				p.y = p.y + 30;
				dateChooser.showDateChooser(p);
			}
		}); 
	}
	
	
	/**
	 * reset the time to current time and 
     * EDALDatePrecision.SECOND as current Precision
	 */
	public void reset()
	{
		this.showcalendar = Calendar.getInstance();
		this.showprecision = EdalDatePrecision.SECOND;
		text.setText("");
	}
	
	/**
     * Returns the Calendar, which is selected by user.
     *
     * @return  the Calendar, which is selected by user.
     */
	public Calendar getCalendar() {
		return this._calendar;
	}
	
	/**
     * Returns the EDALDatePrecision, which is selected by user.
     *
     * @return  the EDALDatePrecision, which is selected by user.
     */
	public EdalDatePrecision getPrecision() {
		return this._precision;
	}

	private void setDate(Date date) {
		text.setText(EdalDateFormat.getDefaultDateFormat(showprecision).format(date));
	}

	private Date getDate() {
		return this.showcalendar.getTime();
	}

	private class DateChooser extends JPanel implements ActionListener,
			ChangeListener, MouseListener {
		private static final long serialVersionUID = 1L;
		int startYear = 1;
		int lastYear = 5000;
		int width = 750;
		int height = 280;

		Color backGroundColor = Color.gray;
		Color palletTableColor = Color.white;
		Color todayBackColor = Color.orange;
		Color weekFontColor = Color.blue;
		Color dateFontColor = Color.black;
		Color weekendFontColor = Color.red;
		Color controlLineColor = Color.pink;
		Color controlTextColor = Color.white;

		JDialog dialog;
		JSpinner yearSpin;
		JSpinner monthSpin;
		JSpinner daySpin;
		JSpinner hourSpin;
		JSpinner minuteSpin;
		JSpinner secondSpin;
		JSpinner millisecondSpin;

		JButton[][] daysButton = new JButton[6][7];

		DateChooser() {
			setLayout(new BorderLayout());
			setBorder(new LineBorder(backGroundColor, 2));
			setBackground(backGroundColor);

			JPanel mainPane = new JPanel();
			mainPane.setLayout(new BorderLayout());

			JPanel toppanel = createprecisionPanel();
			mainPane.add(toppanel, BorderLayout.NORTH);
			JPanel controlpanel = createYearAndMonthPanel();
			mainPane.add(controlpanel, BorderLayout.CENTER);
			JPanel displaypanel = createWeekAndDayPanel();
			mainPane.add(displaypanel, BorderLayout.SOUTH);

			JPanel buttonPane = new JPanel(new FlowLayout(FlowLayout.CENTER, 5,
					5));
			JButton savebtn = new JButton(okAction);
			JButton cancelbtn = new JButton(cancelAction);
			buttonPane.add(savebtn);
			buttonPane.add(cancelbtn);

			add(mainPane, BorderLayout.CENTER);
			add(buttonPane, BorderLayout.SOUTH);
		}

		private JPanel createprecisionPanel() {
			JPanel result = new JPanel();
			result.setLayout(new FlowLayout());

			ButtonGroup g = new ButtonGroup();

			final JRadioButton centuryrb = new JRadioButton("CENTURY");
			if (showprecision != null
					&& showprecision.equals(EdalDatePrecision.CENTURY)) {
				centuryrb.setSelected(true);
			}
			centuryrb.addActionListener(this);

			g.add(centuryrb);
			result.add(centuryrb);

			JRadioButton decaderb = new JRadioButton("DECADE");
			if (showprecision != null
					&& showprecision.equals(EdalDatePrecision.DECADE)) {
				decaderb.setSelected(true);
			}
			decaderb.addActionListener(this);
			g.add(decaderb);
			result.add(decaderb);

			JRadioButton yearrb = new JRadioButton("YEAR");
			if (showprecision != null
					&& showprecision.equals(EdalDatePrecision.YEAR)) {
				yearrb.setSelected(true);
			}
			yearrb.addActionListener(this);
			g.add(yearrb);
			result.add(yearrb);

			JRadioButton monthrb = new JRadioButton("MONTH");
			if (showprecision != null
					&& showprecision.equals(EdalDatePrecision.MONTH)) {
				monthrb.setSelected(true);
			}
			monthrb.addActionListener(this);
			g.add(monthrb);
			result.add(monthrb);

			JRadioButton dayrb = new JRadioButton("DAY");
			if (showprecision != null
					&& showprecision.equals(EdalDatePrecision.DAY)) {
				dayrb.setSelected(true);
			}
			dayrb.addActionListener(this);
			g.add(dayrb);
			result.add(dayrb);

			JRadioButton hourrb = new JRadioButton("HOUR");
			if (showprecision != null
					&& showprecision.equals(EdalDatePrecision.HOUR)) {
				hourrb.setSelected(true);
			}
			hourrb.addActionListener(this);
			g.add(hourrb);
			result.add(hourrb);

			JRadioButton minuterb = new JRadioButton("MINUTE");
			if (showprecision != null
					&& showprecision.equals(EdalDatePrecision.MINUTE)) {
				minuterb.setSelected(true);
			}
			minuterb.addActionListener(this);
			g.add(minuterb);
			result.add(minuterb);

			JRadioButton secondrb = new JRadioButton("SECOND");
			if (showprecision != null
					&& showprecision.equals(EdalDatePrecision.SECOND)) {
				secondrb.setSelected(true);
			}
			secondrb.addActionListener(this);
			g.add(secondrb);
			result.add(secondrb);

			JRadioButton millisecondrb = new JRadioButton("MILLISECOND");
			if (showprecision != null
					&& showprecision.equals(EdalDatePrecision.MILLISECOND)) {
				millisecondrb.setSelected(true);
			}
			millisecondrb.addActionListener(this);
			g.add(millisecondrb);
			result.add(millisecondrb);

			if (showprecision == null) {
				secondrb.setSelected(true);
			}

			return result;
		}

		private JPanel createYearAndMonthPanel() {
			Calendar c = getCalendar();
			int currentYear = c.get(Calendar.YEAR);
			int currentMonth = c.get(Calendar.MONTH) + 1;
			int currentday = c.get(Calendar.DAY_OF_MONTH);
			int currentHour = c.get(Calendar.HOUR_OF_DAY);
			int currentMinute = c.get(Calendar.MINUTE);
			int currentSecond = c.get(Calendar.SECOND);
			int currentMillisecond = c.get(Calendar.MILLISECOND);

			JPanel result = new JPanel();
			result.setLayout(new FlowLayout());
			result.setBackground(controlLineColor);

			JLabel yearLabel = new JLabel("Year");
			yearLabel.setForeground(controlTextColor);
			result.add(yearLabel);

			yearSpin = new JSpinner(new SpinnerNumberModel(currentYear,
					startYear, lastYear, 1));
			yearSpin.setPreferredSize(new Dimension(64, 24));
			yearSpin.setName("Year");
			yearSpin.setEditor(new JSpinner.NumberEditor(yearSpin, "####"));
			yearSpin.addChangeListener(this);
			result.add(yearSpin);

			JLabel monthLabel = new JLabel("Month");
			monthLabel.setForeground(controlTextColor);
			result.add(monthLabel);

			monthSpin = new JSpinner(new SpinnerNumberModel(currentMonth, 1,
					12, 1));
			monthSpin.setPreferredSize(new Dimension(50, 24));
			monthSpin.setName("Month");
			monthSpin.addChangeListener(this);
			result.add(monthSpin);

			JLabel dayLabel = new JLabel("Day");
			dayLabel.setForeground(controlTextColor);
			result.add(dayLabel);

			daySpin = new JSpinner(getdaymodel(currentYear, currentMonth,
					currentday));
			daySpin.setPreferredSize(new Dimension(50, 24));
			daySpin.setName("Day");
			daySpin.addChangeListener(this);
			result.add(daySpin);

			JLabel hourLabel = new JLabel("Hour");
			hourLabel.setForeground(controlTextColor);
			result.add(hourLabel);

			hourSpin = new JSpinner(new SpinnerNumberModel(currentHour, 0, 23,
					1));
			hourSpin.setPreferredSize(new Dimension(50, 24));
			hourSpin.setName("Hour");
			hourSpin.addChangeListener(this);
			result.add(hourSpin);

			JLabel minuteLabel = new JLabel("Minute");
			minuteLabel.setForeground(controlTextColor);
			result.add(minuteLabel);

			minuteSpin = new JSpinner(new SpinnerNumberModel(currentMinute, 0,
					59, 1));
			minuteSpin.setPreferredSize(new Dimension(50, 24));
			minuteSpin.setName("Minute");
			minuteSpin.addChangeListener(this);
			result.add(minuteSpin);

			JLabel secondLabel = new JLabel("Second");
			secondLabel.setForeground(controlTextColor);
			result.add(secondLabel);

			secondSpin = new JSpinner(new SpinnerNumberModel(currentSecond, 0,
					59, 1));
			secondSpin.setPreferredSize(new Dimension(50, 24));
			secondSpin.setName("Second");
			secondSpin.addChangeListener(this);
			result.add(secondSpin);

			JLabel millisecondLabel = new JLabel("Millisecond");
			millisecondLabel.setForeground(controlTextColor);
			result.add(millisecondLabel);

			millisecondSpin = new JSpinner(new SpinnerNumberModel(
					currentMillisecond, 0, 999, 1));
			millisecondSpin.setPreferredSize(new Dimension(55, 24));
			millisecondSpin.setName("Millisecond");
			millisecondSpin.addChangeListener(this);
			result.add(millisecondSpin);

			return result;
		}

		private SpinnerNumberModel getdaymodel(int currentYear,
				int currentMonth, int currentday) {
			int minday = 1;
			int maxday = 30;
			if (currentMonth == 1 || currentMonth == 3 || currentMonth == 5
					|| currentMonth == 7 || currentMonth == 8
					|| currentMonth == 10 || currentMonth == 12) {
				maxday = 31;
			} else if (currentMonth == 2) {
				if (isleapyear(currentYear)) {
					maxday = 29;
				} else {
					maxday = 28;
				}
			}
			return new SpinnerNumberModel(currentday, minday, maxday, 1);
		}

		private boolean isleapyear(int year) {
			if (year % 100 == 0) {
				if (year % 400 == 0) {
					return true;
				}
			} else {
				if (year % 4 == 0) {
					return true;
				}
			}
			return false;
		}

		private JPanel createWeekAndDayPanel() {
			String colname[] = { "Sunday", "Monday", "Tuesday ", "Wednesday",
					"Thursday", "Friday", "Saturday " };
			JPanel result = new JPanel();

			result.setFont(FONT);
			result.setLayout(new GridLayout(7, 7));
			result.setBackground(Color.white);
			JLabel cell;

			for (int i = 0; i < 7; i++) {
				cell = new JLabel(colname[i]);
				cell.setHorizontalAlignment(JLabel.CENTER);
				if (i == 0 || i == 6)
					cell.setForeground(weekendFontColor);
				else
					cell.setForeground(weekFontColor);
				result.add(cell);
			}
			
			int actionCommandId = 0;
			for (int i = 0; i < 6; i++)
				for (int j = 0; j < 7; j++) {
					JButton numberButton = new JButton();
					numberButton.setBorder(null);
					numberButton.setHorizontalAlignment(SwingConstants.CENTER);
					numberButton.setActionCommand(String
							.valueOf(actionCommandId));
					numberButton.addActionListener(this);
					numberButton.addMouseListener(this);
					numberButton.setBackground(palletTableColor);
					numberButton.setForeground(dateFontColor);
					if (j == 0 || j == 6)
						numberButton.setForeground(weekendFontColor);
					else
						numberButton.setForeground(dateFontColor);
					
					daysButton[i][j] = numberButton;
					result.add(numberButton);
					actionCommandId++;
				}

			return result;
		}

		private JDialog createDialog(Frame owner) {
			JDialog result = new JDialog(owner, "DatetimePicker", true);
			result.addWindowListener(createAppCloser());
			result.getContentPane().add(this, BorderLayout.CENTER);
			result.pack();
			result.setSize(width, height);
			return result;
		}

		private JDialog createDialog(JDialog owner) {
			JDialog result = new JDialog(owner, "DatetimePicker", true);
			result.addWindowListener(createAppCloser());
			result.getContentPane().add(this, BorderLayout.CENTER);
			result.pack();
			result.setSize(width, height);
			return result;
		}

		void showDateChooser(Point position) {
			if (SwingUtilities.getWindowAncestor(EdalDateTimePicker.this) != null
					&& (SwingUtilities
							.getWindowAncestor(EdalDateTimePicker.this) instanceof JDialog)) {
				JDialog owner = (JDialog) SwingUtilities
						.getWindowAncestor(EdalDateTimePicker.this);
				if (dialog == null || dialog.getOwner() != owner)
					dialog = createDialog(owner);
				dialog.setLocation(getAppropriateLocation(owner, position));
			} else {
				Frame owner = (Frame) SwingUtilities
						.getWindowAncestor(EdalDateTimePicker.this);
				if (dialog == null || dialog.getOwner() != owner)
					dialog = createDialog(owner);
				dialog.setLocation(getAppropriateLocation(owner, position));
			}

			flushWeekAndDay();
			dialog.setVisible(true);
		}

		Point getAppropriateLocation(Frame owner, Point position) {
			Point result = new Point(position);
			Point p = owner.getLocation();
			int offsetX = (position.x + width) - (p.x + owner.getWidth());
			int offsetY = (position.y + height) - (p.y + owner.getHeight());
			if (offsetX > 0) {
				result.x -= offsetX;
			}

			if (offsetY > 0) {
				result.y -= offsetY;
			}
			return result;
		}

		Point getAppropriateLocation(JDialog owner, Point position) {
			Point result = new Point(position);
			Point p = owner.getLocation();
			int offsetX = (position.x + width) - (p.x + owner.getWidth());
			int offsetY = (position.y + height) - (p.y + owner.getHeight());
			if (offsetX > 0) {
				result.x -= offsetX;
			}

			if (offsetY > 0) {
				result.y -= offsetY;
			}
			return result;
		}

		private Calendar getCalendar() {
			if (showcalendar == null) {
				showcalendar = Calendar.getInstance();
			}
			showcalendar.setTime(getDate());
			return showcalendar;
		}

		private int getSelectedYear() {
			return ((Integer) yearSpin.getValue()).intValue();
		}

		private int getSelectedMonth() {
			return ((Integer) monthSpin.getValue()).intValue();
		}

		private int getSelectedDay() {
			return ((Integer) daySpin.getValue()).intValue();
		}

		private int getSelectedHour() {
			return ((Integer) hourSpin.getValue()).intValue();
		}

		private int getSelectedMinite() {
			return ((Integer) minuteSpin.getValue()).intValue();
		}

		private int getSelectedSecond() {
			return ((Integer) secondSpin.getValue()).intValue();
		}

		private int getSelectedMillisecond() {
			return ((Integer) millisecondSpin.getValue()).intValue();
		}

		private void flushWeekAndDay() {
			Calendar c = getCalendar();
			c.set(Calendar.DAY_OF_MONTH, 1);
			int maxDayNo = c.getActualMaximum(Calendar.DAY_OF_MONTH);
			int dayNo = 2 - c.get(Calendar.DAY_OF_WEEK);
			for (int i = 0; i < 6; i++) {
				for (int j = 0; j < 7; j++) {
					String s = "";
					if (dayNo >= 1 && dayNo <= maxDayNo)
						s = String.valueOf(dayNo);
					daysButton[i][j].setText(s);
					dayNo++;
					
					if (j == 0 || j == 6)
						daysButton[i][j].setForeground(weekendFontColor);
					else
						daysButton[i][j].setForeground(dateFontColor);
				}
			}
		}

		private void refreshdayspin(int currentYear, int currentMonth,
				int currentday) {
			daySpin.setModel(getdaymodel(currentYear, currentMonth, currentday));
			daySpin.updateUI();
		}

		public void stateChanged(ChangeEvent e) {
			JSpinner source = (JSpinner) e.getSource();
			Calendar c = getCalendar();
			if (source.getName().equals("Hour")) {
				c.set(Calendar.HOUR_OF_DAY, getSelectedHour());
				setDate(c.getTime());
				return;
			}
			if (source.getName().equals("Minute")) {
				c.set(Calendar.MINUTE, getSelectedMinite());
				setDate(c.getTime());
				return;
			}
			if (source.getName().equals("Second")) {
				c.set(Calendar.SECOND, getSelectedSecond());
				setDate(c.getTime());
				return;
			}

			if (source.getName().equals("Millisecond")) {
				c.set(Calendar.MILLISECOND, getSelectedMillisecond());
				setDate(c.getTime());
				return;
			}

			
			if (source.getName().equals("Year")) {
				c.set(Calendar.YEAR, getSelectedYear());
				refreshdayspin(getSelectedYear(), getSelectedMonth(),
						getSelectedDay());
			} else if (source.getName().equals("Month")) {
				c.set(Calendar.MONTH, getSelectedMonth() - 1);
				refreshdayspin(getSelectedYear(), getSelectedMonth(),
						getSelectedDay());
			}
			setDate(c.getTime());
			flushWeekAndDay();
		}

		public void actionPerformed(ActionEvent e) {
			String classname = e.getSource().getClass().getName();
			if (classname.equals("javax.swing.JButton")) {
				JButton source = (JButton) e.getSource();
				if (source.getText().length() == 0)
					return;
				
				source.setForeground(todayBackColor);
				int newDay = Integer.parseInt(source.getText());
				daySpin.setValue(Integer.valueOf(newDay));
			} else if (classname.equals("javax.swing.JRadioButton")) {
				JRadioButton source = (JRadioButton) e.getSource();
				if (source.isSelected()) {
					if (source.getText().equals("CENTURY")) {
						monthSpin.setEnabled(false);
						daySpin.setEnabled(false);
						hourSpin.setEnabled(false);
						minuteSpin.setEnabled(false);
						secondSpin.setEnabled(false);
						millisecondSpin.setEnabled(false);
						enabledisplaybuttons(false);
						showprecision = EdalDatePrecision.CENTURY;
					} else if (source.getText().equals("DECADE")) {
						monthSpin.setEnabled(false);
						daySpin.setEnabled(false);
						hourSpin.setEnabled(false);
						minuteSpin.setEnabled(false);
						secondSpin.setEnabled(false);
						millisecondSpin.setEnabled(false);
						enabledisplaybuttons(false);
						showprecision = EdalDatePrecision.DECADE;
					} else if (source.getText().equals("YEAR")) {
						monthSpin.setEnabled(false);
						daySpin.setEnabled(false);
						hourSpin.setEnabled(false);
						minuteSpin.setEnabled(false);
						secondSpin.setEnabled(false);
						millisecondSpin.setEnabled(false);
						enabledisplaybuttons(false);
						showprecision = EdalDatePrecision.YEAR;
					} else if (source.getText().equals("MONTH")) {
						yearSpin.setEnabled(true);
						monthSpin.setEnabled(true);
						daySpin.setEnabled(false);
						hourSpin.setEnabled(false);
						minuteSpin.setEnabled(false);
						secondSpin.setEnabled(false);
						millisecondSpin.setEnabled(false);
						enabledisplaybuttons(false);
						showprecision = EdalDatePrecision.MONTH;
					} else if (source.getText().equals("DAY")) {
						yearSpin.setEnabled(true);
						monthSpin.setEnabled(true);
						daySpin.setEnabled(true);
						hourSpin.setEnabled(false);
						minuteSpin.setEnabled(false);
						secondSpin.setEnabled(false);
						millisecondSpin.setEnabled(false);
						enabledisplaybuttons(true);
						showprecision = EdalDatePrecision.DAY;
					} else if (source.getText().equals("HOUR")) {
						yearSpin.setEnabled(true);
						monthSpin.setEnabled(true);
						daySpin.setEnabled(true);
						hourSpin.setEnabled(true);
						minuteSpin.setEnabled(false);
						secondSpin.setEnabled(false);
						millisecondSpin.setEnabled(false);
						enabledisplaybuttons(true);
						showprecision = EdalDatePrecision.HOUR;
					} else if (source.getText().equals("MINUTE")) {
						yearSpin.setEnabled(true);
						monthSpin.setEnabled(true);
						daySpin.setEnabled(true);
						hourSpin.setEnabled(true);
						minuteSpin.setEnabled(true);
						secondSpin.setEnabled(false);
						millisecondSpin.setEnabled(false);
						enabledisplaybuttons(true);
						showprecision = EdalDatePrecision.MINUTE;
					} else if (source.getText().equals("SECOND")) {
						yearSpin.setEnabled(true);
						monthSpin.setEnabled(true);
						daySpin.setEnabled(true);
						hourSpin.setEnabled(true);
						minuteSpin.setEnabled(true);
						secondSpin.setEnabled(true);
						millisecondSpin.setEnabled(false);
						enabledisplaybuttons(true);
						showprecision = EdalDatePrecision.SECOND;
					} else if (source.getText().equals("MILLISECOND")) {
						yearSpin.setEnabled(true);
						monthSpin.setEnabled(true);
						daySpin.setEnabled(true);
						hourSpin.setEnabled(true);
						minuteSpin.setEnabled(true);
						secondSpin.setEnabled(true);
						millisecondSpin.setEnabled(true);
						enabledisplaybuttons(true);
						showprecision = EdalDatePrecision.MILLISECOND;
					}
				}
			}
		}

		private void enabledisplaybuttons(boolean enable) {
			for (int i = 0; i < daysButton.length; i++) {
				for (int j = 0; j < daysButton[i].length; j++) {
					daysButton[i][j].setEnabled(enable);
				}
			}
		}

		private int formatyeartocentury(int year) {
			if (year < 100) {
				return 0;
			}
			int century = year / 100;
			return (century) * 100;
		}

		private int formatyeartodecade(int year) {
			if (year < 10) {
				return 0;
			}
			int century = year / 10;
			return (century) * 10;
		}

		private void refreshtime() {
			if (showcalendar == null) {
				showcalendar = getCalendar();
			}
			

			if (showprecision != null
					&& showprecision.equals(EdalDatePrecision.CENTURY)) {
				showcalendar.set(Calendar.YEAR,
						formatyeartocentury(getSelectedYear()));
			} else if (showprecision != null
					&& showprecision.equals(EdalDatePrecision.DECADE)) {
				showcalendar.set(Calendar.YEAR,
						formatyeartodecade(getSelectedYear()));
			} else if (showprecision != null
					&& showprecision.equals(EdalDatePrecision.YEAR)) {
				showcalendar.set(Calendar.YEAR, getSelectedYear());
			} else if (showprecision != null
					&& showprecision.equals(EdalDatePrecision.MONTH)) {
				showcalendar.set(Calendar.YEAR, getSelectedYear());
				showcalendar.set(Calendar.MONTH, getSelectedMonth()-1);
			} else if (showprecision != null
					&& showprecision.equals(EdalDatePrecision.DAY)) {
				showcalendar.set(Calendar.YEAR, getSelectedYear());
				showcalendar.set(Calendar.MONTH, getSelectedMonth()-1);
				showcalendar.set(Calendar.DAY_OF_MONTH, getSelectedDay());
			} else if (showprecision != null
					&& showprecision.equals(EdalDatePrecision.HOUR)) {
				showcalendar.set(Calendar.YEAR, getSelectedYear());
				showcalendar.set(Calendar.MONTH, getSelectedMonth()-1);
				showcalendar.set(Calendar.DAY_OF_MONTH, getSelectedDay());
				showcalendar.set(Calendar.HOUR, getSelectedHour());
			} else if (showprecision != null
					&& showprecision.equals(EdalDatePrecision.MINUTE)) {
				showcalendar.set(Calendar.YEAR, getSelectedYear());
				showcalendar.set(Calendar.MONTH, getSelectedMonth()-1);
				showcalendar.set(Calendar.DAY_OF_MONTH, getSelectedDay());
				showcalendar.set(Calendar.HOUR_OF_DAY, getSelectedHour());
				showcalendar.set(Calendar.MINUTE, getSelectedMinite());
			} else if (showprecision != null
					&& showprecision.equals(EdalDatePrecision.SECOND)) {
				showcalendar.set(Calendar.YEAR, getSelectedYear());
				showcalendar.set(Calendar.MONTH, getSelectedMonth()-1);
				showcalendar.set(Calendar.DAY_OF_MONTH, getSelectedDay());
				showcalendar.set(Calendar.HOUR_OF_DAY, getSelectedHour());
				showcalendar.set(Calendar.MINUTE, getSelectedMinite());
				showcalendar.set(Calendar.SECOND, getSelectedSecond());
			} else if (showprecision != null
					&& showprecision.equals(EdalDatePrecision.MILLISECOND)) {
				showcalendar.set(Calendar.YEAR, getSelectedYear());
				showcalendar.set(Calendar.MONTH, getSelectedMonth()-1);
				showcalendar.set(Calendar.DAY_OF_MONTH, getSelectedDay());
				showcalendar.set(Calendar.HOUR_OF_DAY, getSelectedHour());
				showcalendar.set(Calendar.MINUTE, getSelectedMinite());
				showcalendar.set(Calendar.SECOND, getSelectedSecond());
				showcalendar
						.set(Calendar.MILLISECOND, getSelectedMillisecond());
			}
		}

		private Action okAction = new AbstractAction(Const.OK_BTN_STR) {
			private static final long serialVersionUID = 1L;

			public void actionPerformed(ActionEvent e) {
				_calendar = showcalendar;
				_precision = showprecision;
				refreshtime();
				setDate(showcalendar.getTime());
				dialog.setVisible(false);
			}
		};

		private Action cancelAction = new AbstractAction(Const.CANCEL_BTN_STR) {
			private static final long serialVersionUID = 1L;

			public void actionPerformed(ActionEvent e) {
				dialog.setVisible(false);
			}
		};

		public void mouseClicked(MouseEvent e) {
			JButton source = (JButton) e.getSource();
			if (source.getText().length() == 0)
				return;
			source.setForeground(todayBackColor);
			int newDay = Integer.parseInt(source.getText());
			Calendar c = getCalendar();
			c.set(Calendar.DAY_OF_MONTH, newDay);
			setDate(c.getTime());
			daySpin.setValue(Integer.valueOf(newDay));
		}

		public void mouseEntered(MouseEvent e) {
		}

		public void mouseExited(MouseEvent e) {
		}

		public void mousePressed(MouseEvent e) {
		}

		public void mouseReleased(MouseEvent e) {
		}

		private WindowListener createAppCloser() {
			return new WindowAdapter() {
				@Override
				public void windowClosing(final WindowEvent we) {
					dialog.setVisible(false);
				}
			};
		}
	}
}
